home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / RTrace 1.0 / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-28  |  23.0 KB  |  898 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *  Craig Kolb          - stereo view mode
  11.  *  Rodney Bogart       - depth of field (lens camera model)
  12.  *
  13.  * Redistribution and use in source and binary forms are permitted
  14.  * provided that the above copyright notice and this paragraph are
  15.  * duplicated in all such forms and that any documentation,
  16.  * advertising materials, and other materials related to such
  17.  * distribution and use acknowledge that the software was developed
  18.  * by Antonio Costa, at INESC-Norte. The name of the author and
  19.  * INESC-Norte may not be used to endorse or promote products derived
  20.  * from this software without specific prior written permission.
  21.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  22.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24.  */
  25. #ifdef TURBOC
  26. #define MAIN_MODULE
  27. #endif
  28. #ifndef lint
  29. char            copyright[] =
  30. "@(#) Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.\n\
  31. All rights reserved.\n";
  32. #endif
  33. #include "defs.h"
  34. #include "extern.h"
  35.  
  36.  int ytest;
  37.  int xtest;
  38.  
  39. /**********************************************************************
  40.  *    RAY TRACING - Version 7.3.1                                     *
  41.  *                                                                    *
  42.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  43.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  44.  *    MODIFIED BY: Antonio Costa, INESC-Norte, July 1992              *
  45.  **********************************************************************/
  46.  
  47. /***** Main *****/
  48.  
  49. void
  50. runtime_abort(s)
  51.   char_ptr        s;
  52. {
  53.  
  54. #ifdef THINK_C
  55.  
  56.     /* On the mac, we handle a runtime abort with an error dialog */
  57.     abortive_string_error (s);
  58.  
  59. #else
  60.  
  61.   WRITE(ERROR, "Error: runtime - %s\n", s);
  62.   HALT;
  63.  
  64. #endif
  65.  
  66. }
  67. real
  68. tang(x)
  69.   real            x;
  70. {
  71.   if (ABS(COS(x)) < ROUNDOFF)
  72.     return (COS(x) >= 0.0 ? INFINITY : -INFINITY);
  73.   return (real) tan((double) x);
  74. }
  75. vertex_ptr
  76. vertex_pointer(v, vertices, vertex_top, vertex_bottom)
  77.   REG int         v;
  78.   int            *vertices;
  79.   vertex_ptr     *vertex_top, *vertex_bottom;
  80. {
  81.   REG int         i;
  82.   REG vertex_ptr  vertex;
  83.  
  84.   if (v > *vertices)
  85.   {
  86.     if (*vertices == 0)
  87.     {
  88.       ALLOCATE(*vertex_top, vertex_struct, 1);
  89.       *vertex_bottom = *vertex_top;
  90.       *vertices = 1;
  91.     } else
  92.     {
  93.       *vertex_bottom = *vertex_top;
  94.       for (i = 2; i <= *vertices; POSINC(i))
  95.         *vertex_bottom = (vertex_ptr) ((*vertex_bottom)->next);
  96.     }
  97.     for (i = SUCC(*vertices); i <= v; POSINC(i))
  98.     {
  99.       ALLOCATE(vertex, vertex_struct, 1);
  100.       (*vertex_bottom)->next = (void_ptr) vertex;
  101.       *vertex_bottom = vertex;
  102.     }
  103.     *vertices = v;
  104.     return *vertex_bottom;
  105.   }
  106.   vertex = *vertex_top;
  107.   for (i = 2; i <= v; POSINC(i))
  108.     vertex = (vertex_ptr) (vertex->next);
  109.   return vertex;
  110. }
  111. static real     tangent_x, tangent_y;
  112. static real     opening_x, opening_y;
  113. static xyz_struct eye_pin_hole, screen_unit_x, screen_unit_y;
  114.  
  115. void
  116. make_vector(p, x, y, delta)
  117.   xyz_ptr         p;
  118.   real            x, y, delta;
  119. {
  120.   REG real        kx, ky;
  121.   xyz_struct      aperture;
  122.  
  123.   if (jittering_mode == 1)
  124.   {
  125.     x += JITTER * delta;
  126.     y += JITTER * delta;
  127.   }
  128.   kx = x * opening_x - tangent_x;
  129.   ky = y * opening_y - tangent_y;
  130.   p->x = kx * screen_x.x + ky * screen_y.x + gaze.x;
  131.   p->y = kx * screen_x.y + ky * screen_y.y + gaze.y;
  132.   p->z = kx * screen_x.z + ky * screen_y.z + gaze.z;
  133.   NORMALIZE(*p);
  134.   if (focal_aperture > ROUNDOFF)
  135.   {
  136.     UNIT_CIRCLE_POINT(kx, ky);
  137.     kx *= focal_aperture;
  138.     ky *= focal_aperture;
  139.     aperture.x = kx * screen_unit_x.x + ky * screen_unit_y.x;
  140.     aperture.y = kx * screen_unit_x.y + ky * screen_unit_y.y;
  141.     aperture.z = kx * screen_unit_x.z + ky * screen_unit_y.z;
  142.     eye.x = eye_pin_hole.x + aperture.x;
  143.     eye.y = eye_pin_hole.y + aperture.y;
  144.     eye.z = eye_pin_hole.z + aperture.z;
  145.     p->x = focal_distance * p->x - aperture.x;
  146.     p->y = focal_distance * p->y - aperture.y;
  147.     p->z = focal_distance * p->z - aperture.z;
  148.     NORMALIZE(*p);
  149.   }
  150. }
  151. void
  152. transform(t, p1, p2)
  153.   xyzw_ptr       t;
  154.   xyz_ptr        p1, p2;
  155. {
  156.   REG real       w;
  157.  
  158.   p2->x = p1->x * t[0].x + p1->y * t[0].y + p1->z * t[0].z + t[0].w;
  159.   p2->y = p1->x * t[1].x + p1->y * t[1].y + p1->z * t[1].z + t[1].w;
  160.   p2->z = p1->x * t[2].x + p1->y * t[2].y + p1->z * t[2].z + t[2].w;
  161.   if (t[3].w == 0.0)
  162.     return;
  163.   w = p1->x * t[3].x + p1->y * t[3].y + p1->z * t[3].z + t[3].w;
  164.   if (ABS(w) < ROUNDOFF)
  165.     return;
  166.   w = 1.0 / w;
  167.   p2->x *= w;
  168.   p2->y *= w;
  169.   p2->z *= w;
  170. }
  171. void
  172. transform_vector(t, p1, v1, p2, v2)
  173.   xyzw_ptr       t;
  174.   xyz_ptr        p1, v1, p2, v2;
  175. {
  176.   xyz_struct     temp;
  177.  
  178.   temp.x = p1->x + v1->x;
  179.   temp.y = p1->y + v1->y;
  180.   temp.z = p1->z + v1->z;
  181.   transform(t, &temp, v2);
  182.   v2->x -= p2->x;
  183.   v2->y -= p2->y;
  184.   v2->z -= p2->z;
  185. }
  186. void
  187. transform_normal_vector(t, p1, v1, v2)
  188.   xyzw_ptr       t;
  189.   xyz_ptr        p1, v1, v2;
  190. {
  191.   /*
  192.    * REG real       w;
  193.    */
  194.   xyz_struct     p2, temp;
  195.  
  196.   STRUCT_ASSIGN(temp, *p1);
  197.   /* Transpost matrix */
  198.   p2.x = temp.x * t[0].x + temp.y * t[1].x + temp.z * t[2].x + t[3].x;
  199.   p2.y = temp.x * t[0].y + temp.y * t[1].y + temp.z * t[2].y + t[3].y;
  200.   p2.z = temp.x * t[0].z + temp.y * t[1].z + temp.z * t[2].z + t[3].z;
  201.   /*
  202.    * w = temp.x * t[0].w + temp.y * t[1].w + temp.z * t[2].w + t[3].w;
  203.    * if (ABS(w) > ROUNDOFF)
  204.    * {
  205.    *   w = 1.0 / w;
  206.    *   p2.x *= w;
  207.    *   p2.y *= w;
  208.    *   p2.z *= w;
  209.    * }
  210.    */
  211.   temp.x += v1->x;
  212.   temp.y += v1->y;
  213.   temp.z += v1->z;
  214.   /* Transpost matrix */
  215.   v2->x = temp.x * t[0].x + temp.y * t[1].x + temp.z * t[2].x;
  216.   v2->y = temp.x * t[0].y + temp.y * t[1].y + temp.z * t[2].y;
  217.   v2->z = temp.x * t[0].z + temp.y * t[1].z + temp.z * t[2].z;
  218.   /*
  219.    * w = temp.x * t[0].w + temp.y * t[1].w + temp.z * t[2].w + t[3].w;
  220.    * if (ABS(w) > ROUNDOFF)
  221.    * {
  222.    *   w = 1.0 / w;
  223.    *   v2->x *= w;
  224.    *   v2->y *= w;
  225.    *   v2->z *= w;
  226.    * }
  227.    */
  228.   v2->x -= p2.x;
  229.   v2->y -= p2.y;
  230.   v2->z -= p2.z;
  231. }
  232. real
  233. transform_distance(t, distance, p1, v1, p2)
  234.   xyzw_ptr       t;
  235.   real           distance;
  236.   xyz_ptr        p1, v1, p2;
  237. {
  238.   xyz_struct     temp1, temp2;
  239.  
  240.   temp1.x = p1->x + v1->x * distance;
  241.   temp1.y = p1->y + v1->y * distance;
  242.   temp1.z = p1->z + v1->z * distance;
  243.   transform(t, &temp1, &temp2);
  244.   temp2.x -= p2->x;
  245.   temp2.y -= p2->y;
  246.   temp2.z -= p2->z;
  247.   return LENGTH(temp2);
  248. }
  249. void
  250. inverse_transform(t1, t2)
  251.   xyzw_ptr        t1, t2;
  252. {
  253.   real            a[4][4];
  254.   real            b[4], c[4], temp[4];
  255.   REG int         row_pivot, i, j, k;
  256.   REG real        row_max, col_max, col_ratio, temp0;
  257.   int             pivot[4];
  258.  
  259.   a[0][0] = t1[0].x;
  260.   a[0][1] = t1[0].y;
  261.   a[0][2] = t1[0].z;
  262.   a[0][3] = t1[0].w;
  263.   a[1][0] = t1[1].x;
  264.   a[1][1] = t1[1].y;
  265.   a[1][2] = t1[1].z;
  266.   a[1][3] = t1[1].w;
  267.   a[2][0] = t1[2].x;
  268.   a[2][1] = t1[2].y;
  269.   a[2][2] = t1[2].z;
  270.   a[2][3] = t1[2].w;
  271.   a[3][0] = t1[3].x;
  272.   a[3][1] = t1[3].y;
  273.   a[3][2] = t1[3].z;
  274.   a[3][3] = t1[3].w;
  275.   /* Pivoting */
  276.   for (i = 0; i <= 3; POSINC(i))
  277.   {
  278.     pivot[i] = i;
  279.     row_max = 0.0;
  280.     for (j = 0; j <= 3; POSINC(j))
  281.       row_max = MAX(row_max, ABS(a[i][j]));
  282.     if (ABS(row_max) < ROUNDOFF)
  283.       runtime_abort("TRANSFORMATION Matrix not invertible");
  284.     temp[i] = row_max;
  285.   }
  286.   for (i = 0; i <= 2; POSINC(i))
  287.   {
  288.     col_max = ABS(a[i][i]) / temp[i];
  289.     row_pivot = i;
  290.     for (j = SUCC(i); j <= 3; POSINC(j))
  291.     {
  292.       col_ratio = ABS(a[j][i]) / temp[j];
  293.       if (col_ratio > col_max)
  294.       {
  295.         col_max = col_ratio;
  296.         row_pivot = j;
  297.       }
  298.     }
  299.     if (ABS(col_max) < ROUNDOFF)
  300.       runtime_abort("TRANSFORMATION Matrix not invertible");
  301.     if (row_pivot > i)
  302.     {
  303.       j = pivot[row_pivot];
  304.       pivot[row_pivot] = pivot[i];
  305.       pivot[i] = j;
  306.       temp0 = temp[row_pivot];
  307.       temp[row_pivot] = temp[i];
  308.       temp[i] = temp0;
  309.       for (j = 0; j <= 3; POSINC(j))
  310.       {
  311.         temp0 = a[row_pivot][j];
  312.         a[row_pivot][j] = a[i][j];
  313.         a[i][j] = temp0;
  314.       }
  315.     }
  316.     for (j = SUCC(i); j <= 3; POSINC(j))
  317.     {
  318.       a[j][i] /= a[i][i];
  319.       temp0 = a[j][i];
  320.       for (k = SUCC(i); k <= 3; POSINC(k))
  321.         a[j][k] -= temp0 * a[i][k];
  322.     }
  323.   }
  324.   if (ABS(a[3][3]) < ROUNDOFF)
  325.     runtime_abort("TRANSFORMATION Matrix not invertible");
  326.   /* Column 1 */
  327.   b[0] = 1.0;
  328.   b[1] = 0.0;
  329.   b[2] = 0.0;
  330.   b[3] = 0.0;
  331.   c[0] = b[pivot[0]];
  332.   for (i = 1; i <= 3; POSINC(i))
  333.   {
  334.     temp0 = 0.0;
  335.     for (j = 0; j <= PRED(i); POSINC(j))
  336.       temp0 += a[i][j] * c[j];
  337.     c[i] = b[pivot[i]] - temp0;
  338.   }
  339.   c[3] /= a[3][3];
  340.   for (i = 2; i >= 0; POSDEC(i))
  341.   {
  342.     temp0 = 0.0;
  343.     for (j = SUCC(i); j <= 3; POSINC(j))
  344.       temp0 += a[i][j] * c[j];
  345.     c[i] = (c[i] - temp0) / a[i][i];
  346.   }
  347.   t2[0].x = c[0];
  348.   t2[1].x = c[1];
  349.   t2[2].x = c[2];
  350.   t2[3].x = c[3];
  351.   /* Column 2 */
  352.   b[0] = 0.0;
  353.   b[1] = 1.0;
  354.   b[2] = 0.0;
  355.   b[3] = 0.0;
  356.   c[0] = b[pivot[0]];
  357.   for (i = 1; i <= 3; POSINC(i))
  358.   {
  359.     temp0 = 0.0;
  360.     for (j = 0; j <= PRED(i); POSINC(j))
  361.       temp0 += a[i][j] * c[j];
  362.     c[i] = b[pivot[i]] - temp0;
  363.   }
  364.   c[3] /= a[3][3];
  365.   for (i = 2; i >= 0; POSDEC(i))
  366.   {
  367.     temp0 = 0.0;
  368.     for (j = SUCC(i); j <= 3; POSINC(j))
  369.       temp0 += a[i][j] * c[j];
  370.     c[i] = (c[i] - temp0) / a[i][i];
  371.   }
  372.   t2[0].y = c[0];
  373.   t2[1].y = c[1];
  374.   t2[2].y = c[2];
  375.   t2[3].y = c[3];
  376.   /* Column 3 */
  377.   b[0] = 0.0;
  378.   b[1] = 0.0;
  379.   b[2] = 1.0;
  380.   b[3] = 0.0;
  381.   c[0] = b[pivot[0]];
  382.   for (i = 1; i <= 3; POSINC(i))
  383.   {
  384.     temp0 = 0.0;
  385.     for (j = 0; j <= PRED(i); POSINC(j))
  386.       temp0 += a[i][j] * c[j];
  387.     c[i] = b[pivot[i]] - temp0;
  388.   }
  389.   c[3] /= a[3][3];
  390.   for (i = 2; i >= 0; POSDEC(i))
  391.   {
  392.     temp0 = 0.0;
  393.     for (j = SUCC(i); j <= 3; POSINC(j))
  394.       temp0 += a[i][j] * c[j];
  395.     c[i] = (c[i] - temp0) / a[i][i];
  396.   }
  397.   t2[0].z = c[0];
  398.   t2[1].z = c[1];
  399.   t2[2].z = c[2];
  400.   t2[3].z = c[3];
  401.   /* Column 4 */
  402.   b[0] = 0.0;
  403.   b[1] = 0.0;
  404.   b[2] = 0.0;
  405.   b[3] = 1.0;
  406.   c[0] = b[pivot[0]];
  407.   for (i = 1; i <= 3; POSINC(i))
  408.   {
  409.     temp0 = 0.0;
  410.     for (j = 0; j <= PRED(i); POSINC(j))
  411.       temp0 += a[i][j] * c[j];
  412.     c[i] = b[pivot[i]] - temp0;
  413.   }
  414.   c[3] /= a[3][3];
  415.   for (i = 2; i >= 0; POSDEC(i))
  416.   {
  417.     temp0 = 0.0;
  418.     for (j = SUCC(i); j <= 3; POSINC(j))
  419.       temp0 += a[i][j] * c[j];
  420.     c[i] = (c[i] - temp0) / a[i][i];
  421.   }
  422.   t2[0].w = c[0];
  423.   t2[1].w = c[1];
  424.   t2[2].w = c[2];
  425.   t2[3].w = c[3];
  426. }
  427. void
  428. normalize_transform(t)
  429.   xyzw_ptr        t;
  430. {
  431.   REG real        k;
  432.  
  433.   if (t[3].w == 0.0)
  434.     return;
  435.   if (ABS(1.0 - t[3].w) < ROUNDOFF)
  436.   {
  437.     if ((ABS(t[3].x) < ROUNDOFF) AND(ABS(t[3].y) < ROUNDOFF)
  438.         AND(ABS(t[3].z) < ROUNDOFF))
  439.       t[3].w = 0.0;
  440.     return;
  441.   }
  442.   k = 1.0 / t[3].w;
  443.   t[0].x *= k;
  444.   t[0].y *= k;
  445.   t[0].z *= k;
  446.   t[0].w *= k;
  447.   t[1].x *= k;
  448.   t[1].y *= k;
  449.   t[1].z *= k;
  450.   t[1].w *= k;
  451.   t[2].x *= k;
  452.   t[2].y *= k;
  453.   t[2].z *= k;
  454.   t[2].w *= k;
  455.   t[3].x *= k;
  456.   t[3].y *= k;
  457.   t[3].z *= k;
  458.   if ((ABS(t[3].x) < ROUNDOFF) AND(ABS(t[3].y) < ROUNDOFF)
  459.       AND(ABS(t[3].z) < ROUNDOFF))
  460.     t[3].w = 0.0;
  461. }
  462. static void
  463. make_view()
  464. {
  465.   REG real        kx, ky;
  466.   xyz_struct      screen_xy;
  467.  
  468.   CROSS_PRODUCT(screen_x, gaze, up);
  469.   NORMALIZE(screen_x);
  470.   CROSS_PRODUCT(screen_y, gaze, screen_x);
  471.   if (view_mode != 0)
  472.   {
  473.     if (stereo_separation < -ROUNDOFF)
  474.       stereo_separation = gaze_distance * -stereo_separation;
  475.     if (view_mode == STEREO_LEFT)
  476.       kx = -0.5 * stereo_separation;
  477.     if (view_mode == STEREO_RIGHT)
  478.       kx = 0.5 * stereo_separation;
  479.     eye.x += kx * screen_x.x;
  480.     eye.y += kx * screen_x.y;
  481.     eye.z += kx * screen_x.z;
  482.     gaze.x = look.x - eye.x;
  483.     gaze.y = look.y - eye.y;
  484.     gaze.z = look.z - eye.z;
  485.     gaze_distance = LENGTH(gaze);
  486.     if (gaze_distance < ROUNDOFF)
  487.       runtime_abort("EYE POINT equal to LOOK POINT in STEREO MODE");
  488.     NORMALIZE(gaze);
  489.     if (ABS(DOT_PRODUCT(gaze, up)) > COS(ANGLE_MIN))
  490.       runtime_abort("bad UP VECTOR in STEREO MODE");
  491.     CROSS_PRODUCT(screen_x, gaze, up);
  492.     NORMALIZE(screen_x);
  493.     CROSS_PRODUCT(screen_y, gaze, screen_x);
  494.   }
  495.   if (focal_distance < ROUNDOFF)
  496.     focal_distance = gaze_distance;
  497.   else
  498.     gaze_distance = focal_distance;
  499.   tangent_x = tang(view_angle_x);
  500.   tangent_y = tang(view_angle_y);
  501.   opening_x = 2.0 / (real) screen_size_x * tangent_x;
  502.   opening_y = 2.0 / (real) screen_size_y * tangent_y;
  503.   kx = gaze_distance * opening_x;
  504.   ky = gaze_distance * opening_y;
  505.   screen_xy.x = kx * screen_x.x + ky * screen_y.x;
  506.   screen_xy.y = kx * screen_x.y + ky * screen_y.y;
  507.   screen_xy.z = kx * screen_x.z + ky * screen_y.z;
  508.   pixel_distance = LENGTH(screen_xy);
  509.   threshold_distance = pixel_distance * DISTANCE_FACTOR;
  510.   if (focal_aperture > ROUNDOFF)
  511.   {
  512.     STRUCT_ASSIGN(eye_pin_hole, eye);
  513.     kx *= (real) screen_size_x;
  514.     ky *= (real) screen_size_y;
  515.     screen_unit_x.x = kx * screen_x.x;
  516.     screen_unit_x.y = kx * screen_x.y;
  517.     screen_unit_x.z = kx * screen_x.z;
  518.     screen_unit_y.x = ky * screen_y.x;
  519.     screen_unit_y.y = ky * screen_y.y;
  520.     screen_unit_y.z = ky * screen_y.z;
  521.   }
  522. }
  523. static void
  524. init_globals()
  525. {
  526.   REG int         i;
  527.  
  528.   /* Rays */
  529.   eye_rays = 0.0;
  530.   shadow_rays = 0.0;
  531.   reflected_rays = 0.0;
  532.   refracted_rays = 0.0;
  533.   ambient_rays = 0.0;
  534.   shadow_hits = 0.0;
  535.   shadow_cache_hits = 0.0;
  536.   /* Intersection tests */
  537.   octant_tests = 0.0;
  538.   bound_tests = 0.0;
  539.   sphere_tests = 0.0;
  540.   box_tests = 0.0;
  541.   patch_tests = 0.0;
  542.   cone_tests = 0.0;
  543.   polygon_tests = 0.0;
  544.   triangle_tests = 0.0;
  545.   text_tests = 0.0;
  546.   csg_tests = 0.0;
  547.   /* Others */
  548.   shade_level = 0;
  549.   shade_level_max = 0;
  550.   ray_node = 0;
  551.   ray_hits = 0.0;
  552.   ray_cache_resets = 0.0;
  553.   ray_cache_hits = 0.0;
  554.   distributed_cache_resets = 0.0;
  555.   distributed_cache_hits = 0.0;
  556.   for (i = 0; i < RAY_SIZE_MAX; POSINC(i))
  557.     ray_cache[i] = NO_OBJECTS;
  558.   pqueue_resets = 0.0;
  559.   pqueue_insertions = 0.0;
  560.   pqueue_extractions = 0.0;
  561.   pixel_divisions = 0.0;
  562.   RANDOM_START;
  563.   if (texture_mode != 0)
  564.     init_texture();
  565. }
  566.  
  567. #ifdef THINK_C
  568.  
  569.     /* On the mac, we define this macro (from picture.c) to computer rgb
  570.         colors on the fly. */
  571.  
  572. #define INDEX(v)\
  573. (ROUND(MAX(0.0, MIN((real) INDEX_MAX, (v) * (real) SUCC(INDEX_MAX)))))
  574.  
  575. /* externals */
  576. extern Boolean        show_image_rendering;    /* if TRUE, draw image as we render */
  577. extern WindowPtr    image_window;            /* the image window */
  578. extern CGrafPtr        image_port;                /* offscreen port which contains the image */
  579. extern Boolean        keep_image_in_memory;    /* TRUE if we keep a pixmap in memory */
  580. extern Boolean        image_complete;            /* TRUE if the image is completely rendered */
  581.  
  582.     /* We also declare ray_trace to be void ray_trace() rather than the
  583.         original static void ray_trace() so we can access it from
  584.         macstuff.c */
  585.  
  586. void
  587.  
  588. #else
  589.  
  590. static void
  591.  
  592. #endif
  593.  
  594. ray_trace()
  595. {
  596.   int             x, x0, x1, x_count, y, step;
  597.   real            total_time;
  598.   rgb_struct      color;
  599.   ray_struct      ray;
  600.   pixel_ptr       temp_line;
  601.  
  602. #ifdef THINK_C
  603.  
  604.     RGBColor        this_color;            /* color of the current pixel */
  605.     short            i;                    /* index */
  606.     long            *line_address;        /* base address of one bitmap line */
  607.     unsigned char    red, green, blue;    /* RGB components of one pixel */
  608.     long            pixel;                /* 32-bit pixel */
  609.     long            pixel_count;        /* number of pixels we've drawn */
  610.     GrafPtr            temp_port;            /* temporary storage for current GrafPort */
  611.     char            string[80];            /* used to output to the log window */
  612.  
  613. #endif
  614.  
  615.   make_view();
  616.   total_time = CPU_CLOCK;
  617.  
  618. #ifdef THINK_C
  619.  
  620.     /* Mac only encloses if do_enclose is TRUE */
  621.  
  622.     if (do_enclose)
  623.         {
  624.         enclose_all();
  625.  
  626.         /* Update the status window to say we're rendering */
  627.         if (status_dialog_visible) set_status_text("\pRendering…");
  628.         }
  629.  
  630.  
  631.     /* On the mac, we have a status bar to show the proportion of the
  632.         image which has been rendered.  Here we set the maximum to the
  633.         height of the image */
  634.     set_progress_bar_max(screen_size_y);
  635.  
  636. #else
  637.   
  638.   enclose_all();
  639.  
  640. #endif
  641.  
  642.   if (verbose_mode > 1)
  643.   {
  644.     WRITE(results, "Info: enclosing - %g second(s) CPU time\n",
  645.           (CPU_CLOCK - total_time) / 1000.0);
  646.     FLUSH(results);
  647.   }
  648.  
  649.   init_picture();
  650.   init_globals();
  651.   ray.level.r = 1.0;
  652.   ray.level.g = 1.0;
  653.   ray.level.b = 1.0;
  654.   ray.inside = FALSE;
  655.   step = -1;
  656.   total_time = CPU_CLOCK;
  657.  
  658.  ytest = 10;
  659.  xtest = 10; 
  660.   
  661.   
  662.   for (y = 0; y <= screen_size_y; POSINC(y))
  663.   {
  664.     if (step < 0)
  665.     {
  666.       step = 1;
  667.       x = 0;
  668.       x1 = 1;
  669.       x0 = 0;
  670.     } else
  671.     {
  672.       step = -1;
  673.       x = screen_size_x;
  674.       x1 = screen_size_x;
  675.       x0 = PRED(screen_size_x);
  676.     }
  677.     for (x_count = 0; x_count <= screen_size_x; POSINC(x_count))
  678.     {
  679.  
  680.  
  681. /***** (enable test to stop at a pixel for debugging) *****
  682. if (y == ytest)
  683.  {
  684.    if (x == xtest) {
  685.       int gotcha = 1;
  686.    }
  687.  }
  688. *****/
  689.  
  690.       REALINC(eye_rays);
  691.       make_vector(&(ray.vector), (real) x, (real) y, 1.0);
  692.       if (intersect_all(NO_OBJECTS, &eye, &ray, &color) > 0.0)
  693.         STRUCT_ASSIGN(new_line[x].color, color);
  694.       else
  695.         STRUCT_ASSIGN(new_line[x].color, back_color);
  696.       new_line[x].id = ray_cache[0];
  697.       if ((y > 0) AND(x_count > 0))
  698.       {
  699.         find_true_color(x1, y, &(old_line[x0]), &(old_line[x1]),
  700.                         &(new_line[x0]), &(new_line[x1]), &(true_color[x1]));
  701.         x1 += step;
  702.         x0 += step;
  703.       }
  704.       x += step;
  705.       
  706.       PROCESS_MAC_EVENT
  707.       
  708.     }
  709.     if (y > 0)
  710.     {
  711.     
  712. #ifdef THINK_C
  713.  
  714.     /* Mac-specific code, executed once each row */
  715.     
  716.     /* Set the progress bar to reflect the portion of the image rendered */
  717.     if (status_dialog_visible) set_progress_bar_value(y);
  718.  
  719.     /* Find base address of line in offscreen bitmap */
  720.     if (keep_image_in_memory)
  721.         line_address = (long *) ( (*(image_port->portPixMap))->baseAddr +
  722.                                     ((y-1) * screen_size_x * 4) );
  723.  
  724.     /* If we are showing the image in the window, or if we are saving it to
  725.         an offscreen pixmap, draw/store this row. */
  726.     if ((show_image_rendering) || (keep_image_in_memory))
  727.         {
  728.         
  729.         /* If we're drawing to a window, set the port to it */
  730.         if (show_image_rendering)
  731.             {
  732.             /* Remember the current port */
  733.             GetPort (&temp_port);
  734.         
  735.             /* Set the port to the image window */
  736.             SetPort (image_window);
  737.             }
  738.         
  739.         for (i = 1; i <= screen_size_x; i++)
  740.             {
  741.             /* Get the pixel color as a 24-bit RGB color */
  742.             red = (unsigned char) (INDEX(true_color[i].r));
  743.             green = (unsigned char) (INDEX(true_color[i].g));
  744.             blue = (unsigned char) (INDEX(true_color[i].b));
  745.  
  746.             /* If we are generating an offscreen bitmap, store this
  747.                 pixel directly into the offscreen bitmap */
  748.             if (keep_image_in_memory)
  749.                 {
  750.                                 
  751.                 pixel = (long) (red << 16) + (long) (green << 8) + (long) blue;;
  752.                 *(line_address + i - 1) = pixel;
  753.                 }
  754.  
  755.             /* If we are drawing in the window, translate the color
  756.                 to 48-bit RGB and plot the pixel */
  757.             if (show_image_rendering)
  758.                 {
  759.                 this_color.red = (short) red << 8;
  760.                 this_color.green = (short) green << 8;
  761.                 this_color.blue = (short) blue << 8;
  762.                 SetCPixel (i-1, y-1, &this_color);
  763.                 }
  764.             
  765.             PROCESS_MAC_EVENT
  766.             
  767.             }
  768.             
  769.         /* If we're drawing to a window, restore the port */
  770.         if (show_image_rendering)
  771.             SetPort (temp_port);
  772.             
  773.         }
  774.     
  775. #endif
  776.  
  777.       line_picture();
  778.       if (verbose_mode > 2)
  779.       {
  780.         WRITE(ERROR, "." );
  781.         FLUSH(ERROR);
  782.         if ( (y % 20) == 0 )            
  783.           WRITE(ERROR, "Line %d completed\n", y);
  784.       }
  785.     }
  786.     temp_line = old_line;
  787.     old_line = new_line;
  788.     new_line = temp_line;
  789.  
  790.   }
  791.  
  792.  
  793.             /* update the amount of free memory */
  794.             update_status_free_memory();
  795.  
  796.   if (picture != OUTPUT)
  797.     CLOSE(picture);
  798.   if (background_mode == 1)
  799.     CLOSE(background);
  800.   if (raw_mode == 1)
  801.     CLOSE(raw_picture);
  802.   if (verbose_mode < 2)
  803.     return;
  804.   WRITE(results, "Resolution %dx%d\n", screen_size_x, screen_size_y);
  805.   WRITE(results, "Total eye rays:          %-0.0f\n", eye_rays);
  806.   WRITE(results, "Total shadow rays:       %-0.0f\n", shadow_rays);
  807.   if (reflected_rays > 0)
  808.     WRITE(results, "Total reflected rays:    %-0.0f\n", reflected_rays);
  809.   if (refracted_rays > 0)
  810.     WRITE(results, "Total refracted rays:    %-0.0f\n", refracted_rays);
  811.   if (ambient_rays > 0)
  812.     WRITE(results, "Total ambient rays:      %-0.0f\n", ambient_rays);
  813.   WRITE(results, "Total shadow hits:       %-0.0f\n", shadow_hits);
  814.   WRITE(results, "Total shadow cache hits: %-0.0f\n", shadow_cache_hits);
  815.   WRITE(results, "Total ray hits:          %-0.0f\n", ray_hits);
  816.   WRITE(results, "Total ray cache resets:  %-0.0f\n", ray_cache_resets);
  817.   WRITE(results, "Total ray cache hits:    %-0.0f\n", ray_cache_hits);
  818.   if (distributed_cache_mode != 0)
  819.   {
  820.     WRITE(results, "Total amb. cache resets: %-0.0f\n",
  821.           distributed_cache_resets);
  822.     WRITE(results, "Total amb. cache hits:   %-0.0f\n",
  823.           distributed_cache_hits);
  824.   }
  825.   WRITE(results, "Total queue resets:      %-0.0f\n", pqueue_resets);
  826.   WRITE(results, "Total queue insertions:  %-0.0f\n", pqueue_insertions);
  827.   WRITE(results, "Total queue extractions: %-0.0f\n", pqueue_extractions);
  828.   WRITE(results, "Total pixel divisions:   %-0.0f\n", pixel_divisions);
  829.   WRITE(results, "Maximum shading level:   %d\n", shade_level_max);
  830.   WRITE(results, "%d Object(s), %d Light(s), %d Surface(s)\n",
  831.         objects, lights, surfaces);
  832.   WRITE(results, "Total octant inclusion tests:      %-0.0f\n", octant_tests);
  833.   if (bound_tests > 0.0)
  834.     WRITE(results, "Total BV intersection tests:       %-0.0f\n",
  835.       bound_tests);
  836.   if (sphere_tests > 0.0)
  837.     WRITE(results, "Total sphere intersection tests:   %-0.0f\n",
  838.           sphere_tests);
  839.   if (box_tests > 0.0)
  840.     WRITE(results, "Total box intersection tests:      %-0.0f\n",
  841.           box_tests);
  842.   if (patch_tests > 0.0)
  843.     WRITE(results, "Total patch intersection tests:    %-0.0f\n",
  844.           patch_tests);
  845.   if (cone_tests > 0.0)
  846.     WRITE(results, "Total cone intersection tests:     %-0.0f\n",
  847.           cone_tests);
  848.   if (polygon_tests > 0.0)
  849.     WRITE(results, "Total polygon intersection tests:  %-0.0f\n",
  850.           polygon_tests);
  851.   if (triangle_tests > 0.0)
  852.     WRITE(results, "Total triangle intersection tests: %-0.0f\n",
  853.           triangle_tests);
  854.   if (text_tests > 0.0)
  855.     WRITE(results, "Total text intersection tests:     %-0.0f\n",
  856.           text_tests);
  857.   if (csg_tests > 0.0)
  858.     WRITE(results, "Total CSG intersection tests:      %-0.0f\n",
  859.           csg_tests);
  860.   if (list_tests > 0.0)
  861.     WRITE(results, "Total list intersection tests:     %-0.0f\n",
  862.           list_tests);
  863.   WRITE(results, "Info: tracing - %g second(s) CPU time\n",
  864.         (CPU_CLOCK - total_time) / 1000.0);
  865.   FLUSH(results);
  866.  
  867.  
  868.             /* update the amount of free memory */
  869.             update_status_free_memory();
  870.  
  871. }
  872. /***** Main program *****/
  873. void
  874. main(parameters, parameter)
  875.   int             parameters;
  876.   char_ptr        parameter[];
  877. {
  878.  
  879. #ifdef THINK_C
  880.  
  881.   /* the Mac does things a little differently here.  It initializes
  882.      RTrace as a Macintosh application, and then it enters a standard
  883.      Macintosh event loop.  It allows the user to open a .sff file using
  884.      the Open... menu, and then it prompts for the RTrace options with
  885.      a dialog box.  Finally, it generates a command line and feeds it
  886.      to RTrace. */
  887.  
  888.   /* Go into the Mac segment (never returns) */
  889.   do_mac();
  890.  
  891. #endif
  892.  
  893.   get_parameters(PRED(parameters), &(parameter[1]));
  894.   get_scene();                  /* Scene in    */
  895.   ray_trace();                  /* Picture out */
  896.   EXIT;                         /* Quit        */
  897. }
  898.